package ua.edu.sumdu.j2se.roman.lab1.model;


import ua.edu.sumdu.j2se.roman.lab1.domain.Task;
import ua.edu.sumdu.j2se.roman.lab1.domain.TaskList;

import java.io.*;
import java.util.Date;
import java.util.Scanner;
/**
 * Author: Radko Roman.
 */

/**
 * This class describes input/output methods
 */
public class TaskStorage {

    /**
     * This method write TaskList object in to the OutputStream by means of step by step writing next attributes:
     * size of the TaskList, titles of the tasks, state of activity, startTime, endTime and repeatInterval.
     *
     * @param   tasks                   collection of the tasks
     * @param   out                     binary output
     * @throws IOException              in case of input/output error
     * @throws IllegalArgumentException in case if out parameter is null
     */
    public static void write(TaskList tasks, OutputStream out) throws IOException {
        if (out == null) {
            throw new IllegalArgumentException("Check your stream");
        }
        DataOutputStream dos = new DataOutputStream(out);
        dos.writeInt(tasks.size());
        for (Task t: tasks) {
            dos.writeUTF(t.getTitle());
            dos.writeBoolean(t.isActive());
            dos.writeLong(t.getStartTime().getTime());
            dos.writeLong(t.getEndTime().getTime());
            dos.writeLong(t.getRepeatInterval());
        }
        dos.flush();
    }

    /**
     * This method write output in binary file.
     *
     * @param   tasks       collection of the tasks
     * @param   filename    the file in which to write the binary code
     * @throws  IOException in case of input/output error
     */
    public static void writeBinary(TaskList tasks, String filename) throws IOException {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(filename);
            write(tasks, fos);
        } finally {
            if (fos != null)
                fos.close();
        }
    }

    /**
     * This method read from InputStream binary stream.
     *
     * @param   tasks                    collection of the tasks
     * @param   in                       binary input
     * @throws IOException               in case of input/output error
     * @throws ClassNotFoundException    thrown when an application tries to load in a class through its string name
     *                                   using, but no definition for the class with the specified name could be found
     * @throws IllegalArgumentException  in case if in parameter is null
     */
    public static void read(TaskList tasks, InputStream in) throws IOException, ClassNotFoundException {
        if (in == null) {
            throw new IllegalArgumentException("Check your stream");
        }
        DataInputStream dis = new DataInputStream(in);
        int size = dis.readInt();
        for (int i = 0; i < size; i++) {
            String title = dis.readUTF();
            boolean activity = dis.readBoolean();
            long sTime = dis.readLong();
            long eTime = dis.readLong();
            long repInterval = dis.readLong();
            Task t = new Task(title, new Date(sTime) ,new Date(eTime) ,repInterval);
            t.setActive(activity);
            tasks.add(t);
        }
    }

    /**
     * This method read from binary file.
     *
     * @param   tasks                   collection of the tasks
     * @param   filename                the file in which contains the binary code
     * @throws  IOException             in case of input/output error
     * @throws  ClassNotFoundException  thrown when an application tries to load in a class through its string name
     *                                  using but, no definition for the class with the specified name could be found
     * @throws  FileNotFoundException   this exception will be thrown when a file does not exist
     */
    public static void readBinary(TaskList tasks, String filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = null;
        try {
            File f = new File(filename);
            if (f.exists()) {
                FileInputStream fis = new FileInputStream(filename);
                read(tasks, fis);
            } else throw new FileNotFoundException("Check your file name");
        } finally {
            if (ois != null)
                ois.close();
        }

    }

    /**
     * This method write output in text stream.
     *
     * @param   tasks                    collection of the tasks
     * @param   out                      text stream
     * @throws  IOException              in case of input/output error
     * @throws  IllegalArgumentException in case if out parameter is null
     */
    public static void write(TaskList tasks, Writer out) throws IOException {
        if (out == null) {
            throw new IllegalArgumentException("Check your stream");
        }
        PrintWriter w = new PrintWriter(out);
        w.println(tasks.size());
        for (Task t: tasks) {
            w.println(t.getTitle());
            w.println(t.isActive());
            w.println(t.getStartTime().getTime());
            w.println(t.getEndTime().getTime());
            w.println(t.getRepeatInterval());
        }
        w.flush();
    }

    /**
     * This method records TaskListObject in text file.
     *
     * @param tasks      collection of the tasks
     * @param filename   the text file in which need to write object
     */
    public static void writeText(TaskList tasks, String filename) throws IOException {
         FileWriter fileWriter = new FileWriter(filename);
         write(tasks, fileWriter);
    }

    /**
     * Gets with scanner TaskList object attributes from Reader object.
     *
     * @param   tasks       collection of the tasks
     * @param   in          in stream
     * @throws  IOException in case of input/output error
     * @throws  IllegalArgumentException in case if in parameter is null
     */
    public static void read(TaskList tasks, Reader in) throws IOException {
        if (in == null) {
            throw new IllegalArgumentException("Check your stream");
        }
        Scanner s = new Scanner(in);
        int size = s.nextInt();
        for (int i = 0; i < size; i++) {
            String title = s.next();
            boolean activity = s.nextBoolean();
            long sTime = s.nextLong();
            long eTime = s.nextLong();
            long repInterval = s.nextLong();

            Task t = new Task(title, new Date(sTime), new Date(eTime), repInterval);
            t.setActive(activity);
            tasks.add(t);
        }
    }

    /**
     * This method reads TaskListObject from text file.
     *
     * @param   tasks                   collection of the tasks
     * @param   filename                text file which contains the object
     * @throws  IOException             in case of input/output error
     * @throws  ClassNotFoundException  thrown when an application tries to load in a class through its string name
     *                                  using, but no definition for the class with the specified name could be found
     * @throws  FileNotFoundException   this exception will be thrown when a file does not exist
     */
    public static void readText(TaskList tasks, String filename) throws IOException, ClassNotFoundException {
        File f = new File(filename);
            if (f.exists()) {
                FileReader flReader = new FileReader(filename);
                read(tasks, flReader);     
            } else throw new FileNotFoundException("Check your file name");
    }
}
